/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.Text;
using MyPhotoIndex.Interfaces.Imaging;
using MyPhotoIndex.Interfaces;
using MyPhotoIndex.Plugins.DataProviders;
using System.Data;
using System.Xml.Serialization;
using MyPhotoIndex.Utilities;
using System.IO;
using MyPhotoIndex.Interfaces.Queries;

namespace MyPhotoIndex.ImageBank
{
    public class SavedQueriesCollection : Singleton<SavedQueriesCollection>, ISavedQueriesCollection
    {
        private ISavedQueriesDataAccessProvider m_dataAccessProvider;
        private List<ISavedQuery> m_list = new List<ISavedQuery>();
        private Dictionary<int, ISavedQuery> m_map = new Dictionary<int, ISavedQuery>();

        #region ISavedQueriesCollection Members

        public event EventHandler<EventArgs> SavedQueriesCollectionLoadedEvent;

        public ISavedQuery this[int index]
        {
            get { return m_list[index]; }
        }

        public ISavedQuery GetById(int id)
        {
            ISavedQuery savedQuery = null;
            if (m_map.TryGetValue(id, out savedQuery) == false)
            {
                return null;
            }

            return savedQuery;
        }

        public int Count
        {
            get { return m_list.Count; }
        }

        public void Save(ISavedQuery savedQuery)
        {
            try
            {
                SavedQuery query2Save = new SavedQuery();
                query2Save.Id = savedQuery.Id;
                query2Save.Name = savedQuery.Name;
                query2Save.WithAnd = savedQuery.WithAnd;
                query2Save.WithOr = savedQuery.WithOr;
                query2Save.Without = savedQuery.Without;
                query2Save.Relation = savedQuery.Relation;

                XmlSerializer serializer = new XmlSerializer(typeof(SavedQuery));
                StringWriter writer = new StringWriter();
                serializer.Serialize(writer, query2Save);

                DataTable queriesDataTable = m_dataAccessProvider.GetSavedQueries();
                DataRow dataRow = null;

                bool addNew = false;
                dataRow = queriesDataTable.Rows.Find(new object[] { query2Save.Id });
                if (dataRow == null)
                {
                    dataRow = queriesDataTable.Rows.Add(new Object[] { query2Save.Id, writer.ToString() });
                    addNew = true;
                }
                else
                {
                    dataRow[(int)SavedQueriesDataSourceColumnId.QueryData] = writer.ToString();
                }

                m_dataAccessProvider.UpdateDataTable(queriesDataTable, false, true);
                queriesDataTable.AcceptChanges();

                savedQuery.Id = (int)dataRow[(int)SavedQueriesDataSourceColumnId.Id];

                if (addNew == true)
                {
                    m_list.Add(savedQuery);
                    m_map.Add(savedQuery.Id, savedQuery);
                }
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
            }
        }

        public void Load(ISavedQueriesDataAccessProvider dataAccessProvider)
        {
            m_dataAccessProvider = dataAccessProvider;

            try
            {
                DataTable dataTable = m_dataAccessProvider.GetSavedQueries();

                foreach (DataRow row in dataTable.Rows)
                {
                    int savedQueryId = 0;
                    string savedQueryData = string.Empty;

                    if (row.IsNull((int)SavedQueriesDataSourceColumnId.Id) == false)
                    {
                        savedQueryId = Convert.ToInt32(row[(int)SavedQueriesDataSourceColumnId.Id]);
                    }

                    if (row.IsNull((int)SavedQueriesDataSourceColumnId.QueryData) == false)
                    {
                        savedQueryData = Convert.ToString(row[(int)SavedQueriesDataSourceColumnId.QueryData]);
                    }

                    if (string.IsNullOrEmpty(savedQueryData) == true)
                    {
                        continue;
                    }

                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(SavedQuery));
                        TextReader reader = new StringReader(savedQueryData);
                        SavedQuery savedQuery = (SavedQuery)serializer.Deserialize(reader);
                        savedQuery.Id = savedQueryId;

                        m_list.Add(savedQuery);
                        m_map.Add(savedQuery.Id, savedQuery);
                    }
                    catch (Exception ex)
                    {
                        Logger.Log(ex);
                    }
                }

                if (SavedQueriesCollectionLoadedEvent != null)
                {
                    SavedQueriesCollectionLoadedEvent.Invoke(this, EventArgs.Empty);
                }
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
            }
        }

        public void Remove(ISavedQuery savedQuery)
        {
            m_list.Remove(savedQuery);
            m_map.Remove(savedQuery.Id);

            DataTable dataTable = m_dataAccessProvider.GetSavedQueries();
            DataRow dataRow = dataTable.Rows.Find(new Object[] { savedQuery.Id });
            if (dataRow == null)
            {
                return;
            }

            dataRow.Delete();
            m_dataAccessProvider.UpdateDataTable(dataTable, false);
        }

        #endregion

        #region IEnumerable<ISavedQuery> Members

        public IEnumerator<ISavedQuery> GetEnumerator()
        {
            return m_list.GetEnumerator();

        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public void Add(object savedQuery)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion
    }
}
